import React, { useState, useEffect, useRef } from 'react'
import styles from './chatBox.module.less'
import { Input } from 'antd'
import { useRequest } from 'alova/client'
import instance from '@/server/index'
import { ReceiveMessageItem } from '@/typings/message'
import MessageItem from '@/components/messageItem'
import * as _ from 'radash'
import { socket } from '@/utils/socket'
import { Snowflake } from '@/utils/snowflake'

const userId = _.random(1, 10000)
const { Search } = Input

const ChatBox = () => {
  const [isUserScrolling, setIsUserScrolling] = useState(false)
  const [message, setMessage] = useState<string>('')
  const endOfMessageRef = useRef<null | HTMLSpanElement>(null)
  const prevMessageLen = useRef<number>(0)
  const messageInfoRef = useRef<null | HTMLDivElement>(null)
  const dataRef = useRef<ReceiveMessageItem[]>(null)

  const snowflake = new Snowflake({ workerId: 1 })

  // 获取消息列表
  const {
    data,
    send: getList,
    update,
  } = useRequest(
    instance.Get('/message/list', {
      transform: (rowData: IResponse<ReceiveMessageItem[]>) => {
        const data = rowData.data
        dataRef.current = data
        return data
      },
    }),
    {
      initialData: [],
      immediate: false,
    }
  )

  // 触发发送消息事件
  const sendMessageHandler = () => {
    const messageData = {
      messageInfo: message,
      sendUser: `用户#${userId}`,
      timestamp: new Date().toLocaleString(),
      nonce: snowflake.NextId(),
    }
    socket.emit('sendMessage', messageData)
    const messageInfo = {
      id: `${socket.id}${Math.random()}`,
      ...messageData,
    }
    update({
      data: [...data, messageInfo],
    })
    dataRef.current = data
    setMessage('')
    setIsUserScrolling(false)
  }

  // 监听消息变化，启动websocket
  useEffect(() => {
    getList()
    socket.connect()
    socket.on('receiveMessage', (res: ReceiveMessageItem) => {
      const index = dataRef.current.find((item) => item.nonce === res.nonce)
      if (!index) {
        update({
          data: [...dataRef.current, res],
        })
      }
    })
    return () => {
      socket.off('receiveMessage')
      socket.disconnect()
    }
  }, [])

  // 监听添加消息之后，需要滚动屏幕
  useEffect(() => {
    if (
      messageInfoRef.current &&
      data.length > prevMessageLen.current &&
      !isUserScrolling
    ) {
      endOfMessageRef.current.scrollIntoView({
        behavior: 'smooth',
        block: 'start',
        inline: 'nearest',
      })
    }
    prevMessageLen.current = data.length
    dataRef.current = data
  }, [data, isUserScrolling])

  // 监听滚动
  const handleScroll = () => {
    if (messageInfoRef.current) {
      const { scrollTop, scrollHeight, clientHeight } = messageInfoRef.current
      const isScrolledToBottom = scrollHeight - scrollTop === clientHeight
      setIsUserScrolling(!isScrolledToBottom)
    }
  }

  return (
    <div className={styles.container}>
      <div
        className={styles.messageList}
        ref={messageInfoRef}
        onScroll={handleScroll}
      >
        {data.map((item) => (
          <MessageItem messageItem={item} key={item.id} />
        ))}
        <span ref={endOfMessageRef}></span>
      </div>
      <div className={styles.inputBox}>
        <Search
          enterButton="发送"
          placeholder="发送到匿名聊天群"
          value={message}
          onInput={(e) => setMessage(e.target.value.trim())}
          onSearch={sendMessageHandler}
        ></Search>
      </div>
    </div>
  )
}

export default ChatBox
